﻿using LinFu.IoC;
using LinFu.IoC.Interfaces;


namespace CoreEx.Database.Query
{
    /// <summary>
    /// Base class that all expression tree nodes derives from.     
    /// </summary>
    public abstract class ExpressionBase : IExpression
    {
        private static IServiceContainer _serviceContainer = Services.ServiceLocator.Container;

        private static IExpressionFactory _expressionFactory;

        private static IQueryTranslator _queryTranslator;

        static ExpressionBase()
        {
            _expressionFactory = _serviceContainer.GetService<IExpressionFactory>();
            _queryTranslator = _serviceContainer.GetService<IQueryTranslator>("System.Data.SqlClient");
        }

       
        public static ExpressionBase operator == (ExpressionBase leftExpression, ExpressionBase rightExpression)
        {
            return _expressionFactory.Eq(leftExpression, rightExpression);                        
        }

        public static ExpressionBase operator == (ExpressionBase leftExpression, object value)
        {
            return _expressionFactory.Eq(leftExpression, _expressionFactory.Constant(value));                        
        }
        
        
        public static ExpressionBase operator !=(ExpressionBase leftExpression, ExpressionBase rightExpression)
        {
            
            
            var expression = _serviceContainer.GetService<IBinaryExpression>("NotEqualExpression");
            expression.LeftExpression = leftExpression;
            expression.RightExpression = rightExpression;
            return (ExpressionBase)expression;
        }


        public static ExpressionBase operator !=(ExpressionBase leftExpression, object value)
        {
            var expression = _serviceContainer.GetService<IBinaryExpression>("NotEqualExpression");
            expression.LeftExpression = leftExpression;
            expression.RightExpression = _serviceContainer.GetService<IExpressionFactory>().Constant(value);
            return (ExpressionBase)expression;
        }

        public static ExpressionBase operator &(ExpressionBase leftExpression, ExpressionBase rightExpression)
        {
            return _expressionFactory.And(leftExpression, rightExpression);                        
        }

        public static ExpressionBase operator >(ExpressionBase leftExpression, ExpressionBase rightExpression)
        {
            var expression = _serviceContainer.GetService<IBinaryExpression>("GreaterThanExpression");
            expression.LeftExpression = leftExpression;
            expression.RightExpression = rightExpression;
            return (ExpressionBase)expression;
        }

        public static ExpressionBase operator <(ExpressionBase leftExpression, ExpressionBase rightExpression)
        {
            var expression = _serviceContainer.GetService<IBinaryExpression>("LessThanExpression");
            expression.LeftExpression = leftExpression;
            expression.RightExpression = rightExpression;
            return (ExpressionBase)expression;
        }

        public static ExpressionBase operator <=(ExpressionBase leftExpression, ExpressionBase rightExpression)
        {
            var expression = _serviceContainer.GetService<IBinaryExpression>("LessOrEqualExpression");
            expression.LeftExpression = leftExpression;
            expression.RightExpression = rightExpression;
            return (ExpressionBase)expression;
        }

        public static ExpressionBase operator >=(ExpressionBase leftExpression, ExpressionBase rightExpression)
        {
            var expression = _serviceContainer.GetService<IBinaryExpression>("GreaterOrEqualExpression");
            expression.LeftExpression = leftExpression;
            expression.RightExpression = rightExpression;
            return (ExpressionBase)expression;
        }

        
        /// <summary>
        /// Gets or sets the alias for the expression.
        /// </summary>        
        string IExpression.Alias { get; set;}

        public ExpressionBase As(string alias)
        {
            return _expressionFactory.Alias(this, alias);            
        }

        public override string ToString()
        {
            if (_queryTranslator != null)
                return _queryTranslator.Translate(this).Sql;
            return base.ToString();
        }



        public override bool Equals(object obj)
        {
            return obj.ToString() == ToString();
        }

        public override int GetHashCode()
        {
            return ToString().GetHashCode();
        }


    }
}
